/*	Grua 

        C.A.D. 						Curso 2011-2012
 	
	Codigo base para la realización de las practicas de CAD

	modulo  etructura.c
	Dibujo de elementos geometricos
=======================================================

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details 
 http://www.gnu.org/copyleft/gpl.html

=======================================================
Queda prohibido cobrar canon por la copia de este software

*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>                   // Libreria de utilidades de OpenGL
#include "castles.h"


/**
 Seccion de los perfiles para la estructura
**/
#define seccion 0.1 

/** 	void caja( float a, float b, float m)

Construye un paralelepipedo alineado con los ejes de
dimension a x b x m. El objeto se construye en el semiespacio y>=0, con el origen en el
centro de la base. 

**/
void caja( float a, float b, float m)
{
    float x,y,z;
    x= a/2;
    z= m/2;
    y = b;

    glShadeModel( GL_FLAT );

    /* Caras transversales */
    glBegin( GL_QUAD_STRIP );{
        glNormal3f( 0.0, 0.0, -1.0 );   /* Vertical hacia atras */
        glVertex3f( x, 0, -z );
        glVertex3f( -x, 0, -z );
        glVertex3f( x, y, -z );
        glVertex3f( -x, y, -z );

        glNormal3f( 0.0, 1.0, 0.0 );       /* Superior, horizontal */
        glVertex3f( x, y, z );
        glVertex3f( -x, y, z );

        glNormal3f( 0.0, 0.0, 1.0 );       /*Vertical delantera*/
        glVertex3f( x, 0, z );
        glVertex3f( -x, 0, z );

        glNormal3f( 0.0, -1.0, 0.0 );       /*Inferior */
        glVertex3f( x, 0, -z );
        glVertex3f( -x, 0, -z );  }
    glEnd();

    /* Costados */
    glBegin( GL_QUADS );{
        glNormal3f( 1.0, 0.0, 0.0 );
        glVertex3f( x, 0, -z );
        glVertex3f( x, y, -z );
        glVertex3f( x, y, z );
        glVertex3f( x, 0, z ); }
    glEnd();


    glBegin( GL_QUADS );{
        glNormal3f( -1.0, 0.0, 0.0 );
        glVertex3f( -x, 0, -z );
        glVertex3f( -x, 0, z );
        glVertex3f( -x, y, z );
        glVertex3f( -x, y, -z ); }
    glEnd(); 
}


void cajaBorde( float a, float b, float m)
{

    float x,y,z;
    x= a/2;
    z= m/2;
    y = b;

    glShadeModel( GL_FLAT );


    /* Caras transversales */
    glBegin( GL_QUAD_STRIP );{
        glNormal3f( 0.0, 0.0, -1.0 );   /* Vertical hacia atras */
        glVertex3f( x, 0, -z );
        glVertex3f( -x, 0, -z );
        glVertex3f( x, y, -z );
        glVertex3f( -x, y, -z );

        glNormal3f( 0.0, 1.0, 0.0 );       /* Superior, horizontal */
        glVertex3f( x, y, z );
        glVertex3f( -x, y, z );

        glNormal3f( 0.0, 0.0, 1.0 );       /*Vertical delantera*/
        glVertex3f( x, 0, z );
        glVertex3f( -x, 0, z );

        glNormal3f( 0.0, -1.0, 0.0 );       /*Inferior */
        glVertex3f( x, 0, -z );
        glVertex3f( -x, 0, -z );  }
    glEnd();

    /* Costados */
    glBegin( GL_QUADS );{
        glNormal3f( 1.0, 0.0, 0.0 );
        glVertex3f( x, 0, -z );
        glVertex3f( x, y, -z );
        glVertex3f( x, y, z );
        glVertex3f( x, 0, z ); }
    glEnd();


    glBegin( GL_QUADS );{
        glNormal3f( -1.0, 0.0, 0.0 );
        glVertex3f( -x, 0, -z );
        glVertex3f( -x, 0, z );
        glVertex3f( -x, y, z );
        glVertex3f( -x, y, -z ); }
    glEnd();

   /* Aristas */
   glPushMatrix();{
       glTranslatef(0,b/2,0);
       glScalef(a,b,m);
       glutWireCube(1.0);
       glScalef(1/a,1/b,1/m);
   }glPopMatrix();

}

/**	void fasloCilindro(float h, float r)

Crea un paralelepipedo con sombreado como phong (simulando un cilindro)
con centro de las bases en 0,0,0 y 0,h,0, y radio de la base r.

**/
void falsoCilindro(float h, float r)
{
    float a2;

    // m= modulo(x1-x0,y1-y0,z1-z0);
    glPushMatrix();
    // glTranslatef(x0,y0,z0);
    //	glRotatef(-180.0*atan2((z1-z0),(x1-x0))/M_PI,0.0,1.0,0.0);
    //	glRotatef(180.0*atan2((y1-y0),sqrt((x1-x0)*(x1-x0)+(z1-z0)*(z1-z0)))/M_PI-90,0.0,0.0,1.0);

    a2= r; //  a/2.0;
    glShadeModel( GL_SMOOTH );

    /* Caras laterales */
    glBegin( GL_QUAD_STRIP );{
        glNormal3f( 1.0, 0.0, -1.0 );
        glVertex3f(  a2, h, -a2 );
        glVertex3f(  a2, 0, -a2 );

        glNormal3f( -1.0, 0.0, -1.0 );
        glVertex3f( -a2, h, -a2 );
        glVertex3f( -a2, 0, -a2 );

        glNormal3f( -1.0, 0.0, 1.0 );
        glVertex3f( -a2, h, a2 );
        glVertex3f( -a2, 0, a2 );

        glNormal3f( 1.0, 0.0, 1.0 );
        glVertex3f(  a2, h, a2 );
        glVertex3f(  a2, 0, a2 );

        glNormal3f( 1.0, 0.0, -1.0 );
        glVertex3f(  a2, h, -a2 );
        glVertex3f(  a2, 0, -a2 );
    }glEnd();
    glShadeModel( GL_FLAT );
    /* Tapas */
    glBegin( GL_QUADS );{
        glNormal3f( 0.0, 1.0, 0.0 );
        glVertex3f( -a2, h, -a2 );
        glVertex3f( -a2, h,  a2 );
        glVertex3f(  a2, h,  a2 );
        glVertex3f(  a2, h, -a2 );
    }glEnd();


    glBegin( GL_QUADS );{
        glNormal3f( 0.0, -1.0, 0.0 );
        glVertex3f( -a2, 0, -a2 );
        glVertex3f(  a2, 0, -a2 );
        glVertex3f(  a2, 0,  a2 );
        glVertex3f( -a2, 0,  a2 );
    }glEnd();

    glPopMatrix();
}	


/**	void falsoCono( float h, float r)

Crea una piramide sombreada como un cono con centro de las bases en
0,0,0, cuspide en  0,h,0, y radio de la base r.

**/
void falsoCono( float h, float r)
{
    float a2,m,norma,n1,n2;

    m=h;
    glPushMatrix();

    a2= r/2.0;
    norma=sqrt(a2*a2+2*m*m);
    n1= a2/norma;
    n2= m/norma;
    glShadeModel( GL_SMOOTH );

    /* Caras transversales */
    glBegin( GL_QUAD_STRIP );{
        glNormal3f( n2, n1, -n2 );
        glVertex3f(  0, m, 0 );
        glVertex3f(  a2, 0, -a2 );

        glNormal3f( -n2, n1, -n2 );
        glVertex3f( 0, m, 0 );
        glVertex3f( -a2, 0, -a2 );

        glNormal3f( -n2, n1, n2 );
        glVertex3f( 0, m,0 );
        glVertex3f( -a2, 0, a2 );

        glNormal3f( n2, n1, n2 );
        glVertex3f(  0, m, 0 );
        glVertex3f(  a2, 0, a2 );

        glNormal3f( n2, n1, -n2 );
        glVertex3f(  0, m, 0 );
        glVertex3f(  a2, 0, -a2 );
    }glEnd();

    glShadeModel( GL_FLAT );
    /* Tapa */
    glBegin( GL_QUADS );{
        glNormal3f( 0.0, -1.0, 0.0 );
        glVertex3f( -a2, 0, -a2 );
        glVertex3f(  a2, 0, -a2 );
        glVertex3f(  a2, 0,  a2 );
        glVertex3f( -a2, 0,  a2 );
    }glEnd();

    glPopMatrix();

}	

/** 	void ejes(float a)

Dibuja unos ejes de tamanyo a

**/
void ejes(float a)
{
    glPushMatrix();{

        falsoCilindro(0.75*a,0.05*a);
        glTranslatef(0.0,0.75*a,0.0);
        falsoCono(0.25*a,0.15*a);
        glPopMatrix();

        glPushMatrix();
        glRotatef(-90.0,0,0,1);
        falsoCilindro(0.75*a,0.05*a);
        glTranslatef(0.0,0.75*a,0.0);
        falsoCono(0.25*a,0.15*a);
        glPopMatrix();

        glPushMatrix();
        glRotatef(90.0,1,0,0);
        falsoCilindro(0.75*a,0.05*a);
        glTranslatef(0.0,0.75*a,0.0);
        falsoCono(0.25*a,0.15*a);
    }glPopMatrix();
}

void creaEsfera( float rad)
{
    glShadeModel( GL_SMOOTH );
    glutSolidSphere(rad, 20, 20);
}

void trayectoria( proyectil * bala)
{
    float t=bala->t, posY=0, posX=0, posZ=0;
    glPushMatrix();{
        glBegin(GL_LINE_STRIP);{
            posY=bala->yInic+bala->vY*t-0.5*gravedad*t*t;
            posX=bala->xInic+bala->vX*t;
            posZ=bala->zInic+bala->vZ*t;
            glVertex3f(posX, posY, posZ);
            for(t; posY>0; t+=0.01){
                posY=bala->yInic+bala->vY*t-0.5*gravedad*t*t;
                posX=bala->xInic+bala->vX*t;
                posZ=bala->zInic+bala->vZ*t;
                glVertex3f(posX, posY, posZ);
            }
            bala->caidaX=posX;
            bala->caidaZ=posZ;
        }glEnd();
    }glPopMatrix();
}


void creaBloque(float dimXCaja, float dimYCaja, float dimZCaja, int x, int y, int z, int col)
{
    //   x    y    z
    int i=0, j=0, k=0, cont=0;
    glPushMatrix();
    glTranslatef((-(x-1)*dimXCaja/2.0),0,(-(z-1)*dimZCaja/2.0));
    for(k=0; k<z; k++)
    {
        glPushMatrix();
        for(j=0; j<y; j++)
        {
            glPushMatrix();
            for(i=0; i<x; i++)
            {
                cajaBorde(dimXCaja,dimYCaja,dimZCaja);
                glTranslatef(dimXCaja,0,0);
            }
            glPopMatrix();
            glTranslatef(0,dimYCaja,0);
        }
        glPopMatrix();
        glTranslatef(0,0,dimZCaja);
    }
    glPopMatrix();
}


void caja2( float a, float b, float m)
{
    glPushMatrix();{
        glTranslatef(0,b/2,0);

        glScalef(a,b,m);        
        //Cubo
        glutSolidCube(1.0);
        //Aristas
        glColor3f(0,0,0);
        glutWireCube(1.0);

        glScalef(1/a,1/b,1/m);
    }glPopMatrix();
}

void dibujaProyectil(proyectil* bala)
{
    int aux;
    glPushMatrix();{
        if(bala->disparado==1)
            glTranslatef(bala->x,0,bala->z);
        else
            glTranslatef(bala->xInic,0,bala->zInic);

        ejes(3);
        if(bala->disparado==1)
            glTranslatef(0,bala->y,0);
        else
            glTranslatef(0,bala->yInic,0);

        glColor3f(0,0,0);
        glShadeModel( GL_SMOOTH );
        glutSolidSphere(bala->radio, 20, 20);

        /* Vector Normal*/
        glBegin(GL_LINE_STRIP);{
            glVertex3f(0.0, 0.0, 0.0);
            glVertex3f(bala->vX, bala->vY-gravedad*bala->t,bala->vZ);
        }glEnd();

//        aux = pick(bala->x,bala->y);
//        if(aux!=-1 ){
//            bloque* Baux= aux;
//            Baux->act=0;
//        }

    }glPopMatrix();
}




void dibujaJugador(jugador* jug){

    //Bala
    dibujaProyectil(&(jug->proy));
    trayectoria(&(jug->proy));

    //Torreones
    float dimXCaja=bloqueBase.Xdim;
    float dimYCaja=bloqueBase.Ydim;
    float dimZCaja=bloqueBase.Zdim;
    int x=jug->torre[0].nBloqX;
    int y=jug->torre[0].nBloqY;
    int z=jug->torre[0].nBloqZ;
    int col=marron;

    int i=0, j=0, k=0, aux=0;


    glPushMatrix();{
    glColor4f(jug->color[0],jug->color[1],jug->color[2],1);
    glTranslatef(dimXCaja*(x)/2,0,dimZCaja*10/2);


        /** Torreon0 **/
        {
        glPushMatrix();
            glTranslatef((-(x-1)*dimXCaja/2.0),0,(-(z-1)*dimZCaja/2.0));
            for(k=0; k<z; k++)
            {
                glPushMatrix();
                for(j=0; j<y; j++)
                {
                    glPushMatrix();
                    for(i=0; i<x; i++)
                    {
                        if(jug->torre[0].Bloque[i][j][k].act==1)
                        {
                            glLoadName( (int)&(jug->torre[0].Bloque[i][j][k]) );
                            cajaBorde(dimXCaja,dimYCaja,dimZCaja);
                        }
                        glTranslatef(dimXCaja,0,0);
                    }
                    glPopMatrix();
                    glTranslatef(0,dimYCaja,0);
                }
                glPopMatrix();
                glTranslatef(0,0,dimZCaja);
            }
        glPopMatrix();
        }

    glTranslatef(0,0,-dimZCaja*10);
        /** Torreon1 **/
        {
        glPushMatrix();
            glTranslatef((-(x-1)*dimXCaja/2.0),0,(-(z-1)*dimZCaja/2.0));
            for(k=0; k<z; k++)
            {
                glPushMatrix();
                for(j=0; j<y; j++)
                {
                    glPushMatrix();
                    for(i=0; i<x; i++)
                    {
                        if(jug->torre[1].Bloque[i][j][k].act==1)
                        {
                            glLoadName( (int)&(jug->torre[1].Bloque[i][j][k]) );
                            cajaBorde(dimXCaja,dimYCaja,dimZCaja);
                        }
                        glTranslatef(dimXCaja,0,0);
                    }
                    glPopMatrix();
                    glTranslatef(0,dimYCaja,0);
                }
                glPopMatrix();
                glTranslatef(0,0,dimZCaja);
            }
            glPopMatrix();
        }


    }glPopMatrix();
}

void actualizaProyectil(proyectil * bala){
    bala->vX=bala->vI*cos(bala->angZ*M_PI/180)*cos(bala->angY*M_PI/180);
    bala->vY=bala->vI*sin(bala->angZ*M_PI/180);
    bala->vZ=bala->vI*cos(bala->angZ*M_PI/180)*sin(bala->angY*M_PI/180);


    if(bala->disparado==1)
    {
        auxY=bala->yInic + bala->vY*bala->t - 0.5*gravedad*bala->t*bala->t;
        if(auxY>0)
        {
            bala->t+=0.025;
            bala->y=auxY;
            bala->x=bala->xInic + bala->vX*bala->t;
            bala->z=bala->zInic + bala->vZ*bala->t;
        }
    }
}

void inicJugador (jugador * jugador){

    //Torreones jugador
    bloque * pBloq;
    jugador->torre[1].nBloqX=jugador->torre[1].nBloqY=jugador->torre[1].nBloqZ=5;
    jugador->torre[0].nBloqX=jugador->torre[0].nBloqY=jugador->torre[0].nBloqZ=5;

    //Base del torreon
    int i,j,k;
    for(i=0; i<5; i++)
        for(j=0; j<4; j++)
            for(k=0; k<5; k++)
            {
                //Torre0
                pBloq=&(jugador->torre[0].Bloque[i][j][k]);
                pBloq->act=1;
                pBloq->x=i;
                pBloq->y=j;
                pBloq->z=k;
                pBloq->vI=pBloq->angY=pBloq->angZ=0;
                pBloq->velY=pBloq->velZ=pBloq->vX=pBloq->t=0;
                pBloq->xInic=pBloq->yInic=pBloq->zInic=0;

                //Torre1
                pBloq=&(jugador->torre[1].Bloque[i][j][k]);
                pBloq->act=1;
                pBloq->x=i;
                pBloq->y=j;
                pBloq->z=k;
                pBloq->vI=pBloq->angY=pBloq->angZ=0;
                pBloq->velY=pBloq->velZ=pBloq->vX=pBloq->t=0;
                pBloq->xInic=pBloq->yInic=pBloq->zInic=0;
            }
    //Almenas del torreon
    for(i=0; i<5; i++)
        for(k=0; k<5; k++)
        {
            pBloq=&(jugador->torre[0].Bloque[i][4][k]);
            if(k%2==0 && i%2==0)
            {
                pBloq->act=1;
                pBloq->x=i;
                pBloq->y=j;
                pBloq->z=k;
                pBloq->vI=pBloq->angY=pBloq->angZ=0;
                pBloq->velY=pBloq->velZ=pBloq->vX=pBloq->t=0;
                pBloq->xInic=pBloq->yInic=pBloq->zInic=0;

                pBloq=&(jugador->torre[1].Bloque[i][4][k]);

                pBloq->act=1;
                pBloq->x=i;
                pBloq->y=j;
                pBloq->z=k;
                pBloq->vI=pBloq->angY=pBloq->angZ=0;
                pBloq->velY=pBloq->velZ=pBloq->vX=pBloq->t=0;
                pBloq->xInic=pBloq->yInic=pBloq->zInic=0;

            }
            else{
                pBloq->act=0;
                pBloq=&(jugador->torre[1].Bloque[i][4][k]);
                pBloq->act=0;
            }
        }

    //Proyectil
    inicProyectil(&(jugador->proy));
}

void inicProyectil (proyectil * pProy){
    pProy->radio=0.75;
    pProy->xInic=pProy->x=21;
    pProy->yInic=pProy->y=pProy->radio;
    pProy->zInic=pProy->z=0;
    pProy->color=marron;

    pProy->masa=10.0;
    pProy->angZ=135;
    pProy->angY=0;
    pProy->vI=20;
    pProy->vX=pProy->vI*cos(pProy->angZ*M_PI/180)*cos(pProy->angY*M_PI/180);
    pProy->vY=pProy->vI*sin(pProy->angZ*M_PI/180);
    pProy->vZ=pProy->vI*cos(pProy->angZ*M_PI/180)*sin(pProy->angY*M_PI/180);
    pProy->t=0;
    pProy->caidaZ=pProy->caidaX=0;

    pProy->velY=1;
    pProy->velZ=1;

    pProy->disparado=0;

    pProy->x=pProy->y=pProy->z=0;

}

void cambioTurno(){

    //Reiniciar lo que se deba del turno actual
    inicProyectil(&(jugadores[turno].proy));
/*
    x_camara= jugadores[turno].proy.xInic + 40 ;		// Posicion de la camara
    y_camara=15;
    z_camara=jugadores[turno].proy.zInic;
    */
    turno=(turno+1)%2;
}
